#include "cvector3f.h"

CVector3f::CVector3f()
{
}

CVector3f::CVector3f(float x, float y, float z)
{
    this->m_fX = x;
    this->m_fY = y;
    this->m_fZ = z;
}

CVector3f::CVector3f(CPoint3f A, CPoint3f B)
{
    this->m_fX = B.GetX() - A.GetX();
    this->m_fY = B.GetY() - A.GetY();
    this->m_fZ = B.GetZ() - A.GetZ();
}

void CVector3f::normalize()
{
    float length = CPoint3f(0.0, 0.0, 0.0).Distance(CPoint3f(this->m_fX, this->m_fY, this->m_fZ));
    this->m_fX /= length;
    this->m_fY /= length;
    this->m_fZ /= length;
}

void CVector3f::operator=(const CVector3f &p)
{
    this->m_fX = p.m_fX;
    this->m_fY = p.m_fY;
    this->m_fZ = p.m_fZ;
}

CPoint3f CVector3f::operator+ (CPoint3f p)
{
        CPoint3f p2(p.GetX() + this->m_fX, p.GetY() + this->m_fY, p.GetZ() + this->m_fZ );
        return p2;
}

CPoint3f CVector3f::operator- (CPoint3f p)
{
        CPoint3f p2(p.GetX() - this->m_fX, p.GetY() - this->m_fY, p.GetZ() - this->m_fZ);
        return p2;
}

CVector3f CVector3f::operator* (float c)
{
        CVector3f v2(this->m_fX *c, this->m_fY * c, this->m_fZ * c );
        return v2;
}

CVector3f CVector3f::operator/ (float c)
{
        CVector3f v2(this->m_fX / c, this->m_fY / c, this->m_fZ / c );
        return v2;
}

CVector3f CVector3f::operator- (CVector3f v)
{
        CVector3f v2(this->m_fX - v.m_fX, this->m_fY - v.m_fY, this->m_fZ - v.m_fZ );
        return v2;
}

float CVector3f::operator* (CVector3f v)
{
        return this->m_fX * v.m_fX + this->m_fY * v.m_fY + this->m_fZ * v.m_fZ;
}

CVector3f CVector3f::operator +(CVector3f v)
{
    return CVector3f(this->m_fX + v.m_fX, this->m_fY + v.m_fY, this->m_fZ + v.m_fZ);
}

CVector3f CVector3f::crossProduct(CVector3f P)
{
    return CVector3f((this->m_fY*P.m_fZ)-(this->m_fZ*P.m_fY),
                      (this->m_fZ*P.m_fX)-(this->m_fX*P.m_fZ),
                      (this->m_fX*P.m_fY)-(this->m_fY*P.m_fX));
}

float CVector3f::length()
{
    return sqrt(this->length2());
}

float CVector3f::length2()
{
    return pow(this->m_fX, 2)+pow(this->m_fY,2)+pow(this->m_fZ,2);
}

float CVector3f::angle(CVector3f V)
{
    float n1 = this->length2(), n2 = V.length2(), scal = V*(*this);
    float angle = acos(scal/sqrt(n1*n2));
    if (angle >= M_PI/2.0 && angle >= M_PI)
        angle -= M_PI;
    else
    if (angle <= -M_PI/2.0 && angle >= -M_PI)
        angle += M_PI;
    return angle;
//	return	acos(((V.x * this->m_fX) + (V.y * this->m_fY) + (V.z * this->m_fZ)) / sqrt((pow(V.x,2)+pow(V.y,2)+pow(V.z,2)) * (pow(this->m_fX,2)+pow(this->m_fY,2)+pow(this->m_fZ,2))));
}

